<template>
  <div ref="gymContainer" class="gym-container"></div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

export default {
  name: "GymModel",
  data() {
    return {
      lightOn: true, // 初始状态为开灯
      streetLight: null,
      pedestrians: []
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.initThreeJS();
    });
  },
  methods: {
    initThreeJS() {
      // 创建场景
      const scene = new THREE.Scene();

      // 创建相机
      const camera = new THREE.PerspectiveCamera(
        75,
        this.$refs.gymContainer.clientWidth /
          this.$refs.gymContainer.clientHeight,
        0.1,
        1000
      );
      camera.position.set(15, 15, 15); // 设置相机位置
      camera.lookAt(0, 0, 0); // 设置相机的观察点

      // 创建渲染器
      const renderer = new THREE.WebGLRenderer({ antialias: true });
      renderer.setSize(
        this.$refs.gymContainer.clientWidth,
        this.$refs.gymContainer.clientHeight
      );
      renderer.setPixelRatio(window.devicePixelRatio); // 设置像素比
      renderer.shadowMap.enabled = true; // 启用阴影
      renderer.setClearColor(0x000000); // 设置背景颜色为黑色
      this.$refs.gymContainer.appendChild(renderer.domElement);

      // 创建建筑模型
      const buildingGeometry = new THREE.BoxGeometry(10, 10, 10);
      const buildingMaterial = new THREE.MeshPhongMaterial({ color: 0xeecece });
      const building = new THREE.Mesh(buildingGeometry, buildingMaterial);
      building.castShadow = true; // 建筑投射阴影
      building.receiveShadow = true; // 建筑接收阴影
      scene.add(building);

      // 创建地板
      const floorGeometry = new THREE.PlaneGeometry(50, 50);
      const floorMaterial = new THREE.MeshPhongMaterial({ color: 0x333333 });
      const floor = new THREE.Mesh(floorGeometry, floorMaterial);
      floor.rotation.x = -Math.PI / 2; // 旋转地板，使其水平
      floor.receiveShadow = true; // 地板接收阴影
      scene.add(floor);

      // 创建街道
      this.createStreets(scene);

      // 创建草地
      this.createGrass(scene);

      // 创建路灯
      this.createStreetLight(scene);

      // 创建行人
      this.createPedestrians(scene);

      // 添加环境光源
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); // 颜色和强度
      scene.add(ambientLight);

      // 添加 OrbitControls 控件
      const controls = new OrbitControls(camera, renderer.domElement);
      controls.enableDamping = true; // 启用阻尼（惯性）
      controls.dampingFactor = 0.25; // 阻尼系数
      controls.screenSpacePanning = false;
      controls.minDistance = 5;
      controls.maxDistance = 50;
      controls.maxPolarAngle = Math.PI / 2; // 限制垂直旋转角度

      // 渲染循环
      const animate = () => {
        requestAnimationFrame(animate);
        controls.update(); // 更新控件
        this.animatePedestrians();
        renderer.render(scene, camera);
      };
      animate();
    },
    createStreets(scene) {
      const streetGeometry = new THREE.BoxGeometry(50, 1, 5);
      const streetMaterial = new THREE.MeshPhongMaterial({ color: 0x888888 });

      // 四条街道
      const streets = [
        { position: [0, 0, -20], rotation: [0, 0, 0] },
        { position: [0, 0, 20], rotation: [0, 0, 0] },
        { position: [-20, 0, 0], rotation: [0, Math.PI / 2, 0] },
        { position: [20, 0, 0], rotation: [0, Math.PI / 2, 0] }
      ];

      streets.forEach(street => {
        const streetMesh = new THREE.Mesh(streetGeometry, streetMaterial);
        streetMesh.position.set(...street.position);
        streetMesh.rotation.set(...street.rotation);
        streetMesh.receiveShadow = true;
        scene.add(streetMesh);
      });
    },
    createGrass(scene) {
      const grassGeometry = new THREE.PlaneGeometry(40, 40);
      const grassMaterial = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
      const grass = new THREE.Mesh(grassGeometry, grassMaterial);
      grass.rotation.x = -Math.PI / 2; // 旋转使其水平
      grass.position.y = 0.01; // 略高于地板
      grass.receiveShadow = true;
      scene.add(grass);
    },
    createStreetLight(scene) {
      // 创建路灯
      const streetLightGeometry = new THREE.CylinderGeometry(0.1, 0.1, 5, 32);
      const streetLightMaterial = new THREE.MeshBasicMaterial({
        color: 0x000000
      });
      const streetLightPole = new THREE.Mesh(
        streetLightGeometry,
        streetLightMaterial
      );
      streetLightPole.position.set(10, 2.5, 0); // 调整路灯位置
      scene.add(streetLightPole);

      const streetLightHeadGeometry = new THREE.SphereGeometry(0.5, 32, 32);
      const streetLightHeadMaterial = new THREE.MeshBasicMaterial({
        color: 0xffff00
      });
      const streetLightHead = new THREE.Mesh(
        streetLightHeadGeometry,
        streetLightHeadMaterial
      );
      streetLightHead.position.set(10, 5, 0); // 调整路灯头的位置
      scene.add(streetLightHead);

      // 添加路灯光源
      const streetLight = new THREE.PointLight(0xffff00, 10, 20); // 增加亮度和照射距离
      streetLight.position.set(10, 5, 0); // 调整路灯光源的位置
      streetLight.castShadow = true; // 路灯投射阴影
      streetLight.shadow.mapSize.width = 1024; // 阴影映射宽度
      streetLight.shadow.mapSize.height = 1024; // 阴影映射高度
      scene.add(streetLight);
      this.streetLight = streetLight;
      this.streetLight.visible = this.lightOn;
    },
    createPedestrians(scene) {
      const pedestrianGeometry = new THREE.BoxGeometry(0.5, 1.5, 0.5);
      const pedestrianMaterial = new THREE.MeshPhongMaterial({ color: 0xff0000 });

      // 创建两个行人
      for (let i = 0; i < 2; i++) {
        const pedestrian = new THREE.Mesh(pedestrianGeometry, pedestrianMaterial);
        pedestrian.position.set(i * 2 - 1, 0.75, 0); // 设置初始位置
        scene.add(pedestrian);
        this.pedestrians.push(pedestrian);
      }
    },
    animatePedestrians() {
      this.pedestrians.forEach((pedestrian, index) => {
        pedestrian.position.x += (index % 2 === 0 ? 0.05 : -0.05); // 移动速度和方向

        // 检查边界，重置位置
        if (pedestrian.position.x > 20) pedestrian.position.x = -20;
        if (pedestrian.position.x < -20) pedestrian.position.x = 20;
      });
    },
    toggleLight() {
      this.lightOn = !this.lightOn;
      this.streetLight.visible = this.lightOn;
    }
  }
};
</script>

<style scoped>
.gym-container {
  width: 100%;
  height: 100%;
}
</style>
